package com.zhang.auth.service;

import com.zhang.auth.config.ErrorLoginConfig;
import com.zhang.common.core.constant.MsgTemplate;
import com.zhang.common.core.constant.RedisKeyConstant;
import com.zhang.common.core.po.auth.ErrorLogin;
import com.zhang.common.core.util.WebUtils;
import com.zhang.common.log.LogService;
import com.zhang.common.log.constant.LogConstant;
import com.zhang.common.security.util.SecurityUtils;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description
 * @Author zsw
 * @Date 2019/11/13 1:03
 * @Version V1.0
 **/
@Service
public class ErrorLoginService {

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    ErrorLoginConfig errorLoginConfig;

    @Autowired
    LogService logService;


    /**
     * 错误三次 锁定登录
     */
    public void loclLoginCheck() {
        if (errorLoginConfig.isEnabled()) {
            String username = SecurityUtils.getUser().getUsername();
            String usernameKey = RedisKeyConstant.ERROR_LOGIN_PREFIX + username;

            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            String ip = WebUtils.getIP(request);
            String ipKey = RedisKeyConstant.ERROR_LOGIN_PREFIX + ip;

            lockLoginCheck(ipKey, String.format(MsgTemplate.ERROR_LOGIN_IP,ip));
            lockLoginCheck(usernameKey, String.format(MsgTemplate.ERROR_LOGIN_USER,username));


        }

    }

    /**
     * 时间过后，重置0
     * @param key
     * @param msg
     */
    private void lockLoginCheck(String key, String msg) {
        boolean b = redisTemplate.hasKey(key);
        if (b) {
            ErrorLogin errorLogin = (ErrorLogin) redisTemplate.opsForValue().get(key);

            //当前错误次数已到阈值，锁住
            if (errorLogin.getErrorCount() >= errorLoginConfig.getMaxErrorCount()) {
                long lastLoginTime = errorLogin.getLastLoginTime().getTime();
                long currentTime = System.currentTimeMillis();

                int s = (int) ((currentTime - lastLoginTime) / 1000);
                int maxS = errorLoginConfig.getMaxIntervalTime() * 60;
                int value = maxS-s;//剩余时间
                if (0 <= value && value < maxS) {

                    logService.saveAuthLoginLog(msg, LogConstant.LOG_LEVEL_ERROR);

                        if ( 0 <= value &&value <= 60) {
                                throw new LockedException(msg + "，请在 " + value + " s 后登录");
                        } else {
                            int a = value / 60 + 1 ;
                            throw new LockedException(msg +"，请在 " + a  + " min 后登录");

                        }

                }else{
                    redisTemplate.delete(key);
                }
            }

        }
    }

//============================================================================================================================

    /**
     *  用户、ip添加错误次数
     * 登陆失败，次数+1，直至第三次 锁定
     * @return 返回当前连续错的次数
     */
    public Map<String,Object> checkErrorLoginCount(){

            String usernameKey = RedisKeyConstant.ERROR_LOGIN_PREFIX + SecurityUtils.getUser().getUsername();

            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String ip = WebUtils.getIP(request);
        String ipKey = RedisKeyConstant.ERROR_LOGIN_PREFIX + ip;
            //检查用户名
            int errorUserCount = checkErrorLoginCount(usernameKey);
            //检查ip
            int errorIpCount = checkErrorLoginCount(ipKey);
            Map<String, Object> map = new HashMap<>();
            map.put("error_user_login_count",errorUserCount);
            map.put("error_ip_login_count",errorIpCount);
            map.put("error_ip",ip);
            return map;

    }


    /**
     * 指定key 添加错误次数
     * @param key
     * @return
     */
    private int checkErrorLoginCount(String key){
        ErrorLogin errorLogin = (ErrorLogin) redisTemplate.opsForValue().get(key);

        int errorCount =0;
        if(errorLogin==null){
            errorCount  += 1;
            redisTemplate.opsForValue().set(key,new ErrorLogin(new Date(),errorCount));

        }
//        else if(errorLogin.getErrorCount() == errorLoginConfig.getMaxErrorCount()){
//            errorCount = errorLogin.getErrorCount()+1;
//        }
        else {
            errorCount = errorLogin.getErrorCount()+ 1;
            redisTemplate.opsForValue().set(key,new ErrorLogin(new Date(),errorCount));
        }

        return errorCount;
    }

    public void suceesLoginDelKey(){


            String usernameKey = RedisKeyConstant.ERROR_LOGIN_PREFIX + SecurityUtils.getUser().getUsername();

            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

            String ipKey = RedisKeyConstant.ERROR_LOGIN_PREFIX + WebUtils.getIP(request);

            //判断该用户上次是否错误登录过
            boolean a = redisTemplate.hasKey(usernameKey);

            if (a) {
                redisTemplate.delete(usernameKey);
            }

            Boolean b = redisTemplate.hasKey(ipKey);

            if (b) {
                redisTemplate.delete(ipKey);
            }

    }


    @Test
    public void test(){
        String encode = new BCryptPasswordEncoder().encode("123456");
        System.out.println(encode);
    }
}